/*
 *
 *   Copyright (C) 2002-2007 by Raymond Huang
 *   plushuang at users.sourceforge.net
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  ---
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU Lesser General Public License in all respects
 *  for all of the code used other than OpenSSL.  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so.  If you
 *  do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 */

#include <urlglib/ug_i18n.h>
#include <gdk/gdkkeysyms.h>
#include "main_window.h"
#include "urlgfe_util.h"
#include "category_tree_view.h"


static void main_menu_init    (MainMenu* mm, MainWindow* mw);
static void main_toolbar_init (MainToolbar* mt);

static void statusbar_set_n_selected (GtkStatusbar* sb, guint n_selected);
static void text_buffer_add_text (GtkTextBuffer* buffer,
                                  GtkTextTag* text_tag,
                                  gchar *name, gchar *str,
                                  gboolean next_line);
                                  

// Signal handler ------------------------------------------------------------

static void on_category_selection_changed (GtkTreeSelection* selection, MainWindow* mw)
{
	if (gtk_tree_selection_count_selected_rows (selection))
		main_window_set_category_sensitive (mw, TRUE);
	else
		main_window_set_category_sensitive (mw, FALSE);
}

static void on_category_row_collapsed (GtkTreeView* tview, GtkTreeIter* iter,
                                       GtkTreePath* path, gpointer user_data)
{
	GtkTreeSelection* selection;

	// select category when row collapsed
	selection = gtk_tree_view_get_selection (tview);
	if (gtk_tree_selection_count_selected_rows (selection)==0)
		gtk_tree_view_set_cursor (tview, path, NULL, FALSE);
}

static void on_download_cursor_changed (GtkTreeView* view, MainWindow* mw)
{
	main_window_message_area_refresh (mw);
}

static void on_download_selection_changed (GtkTreeSelection* selection, MainWindow* mw)
{
	// Don't handle "selection_changed" when moving download.
	if (mw->download_moving)
		return;

	if (gtk_tree_selection_count_selected_rows (selection))
		main_window_set_download_sensitive (mw, TRUE);
	else
		main_window_set_download_sensitive (mw, FALSE);

	main_window_statusbar_refresh (mw);
}

static void on_view_toggled (GtkCheckMenuItem* cmi, gpointer data)
{
	MainWindow* mw = data;

	if (mw->view_setting_loading == FALSE)
		main_window_view_get (mw);

	main_window_view_set (mw);
}


// download view and store signal handler ---------------------------

static gboolean on_download_button_event (GtkWidget* widget,
                                          GdkEventButton* event,
                                          MainWindow* mw)
{
	if (event->type==GDK_BUTTON_PRESS && event->button==3) {
		// press right button
		gtk_menu_popup (mw->menu.download.self,
		                NULL,
		                NULL,
		                NULL,
		                NULL,
		                0,
		                gtk_get_current_event_time());
		return TRUE;
	}
//	main_window_decide_download_sensitive (mw);
	return FALSE;
}

// category view signal handler -------------------------------------
static gboolean on_category_button_event (GtkWidget* widget,
                                          GdkEventButton* event,
                                          MainWindow* mw)
{
	if (event->type==GDK_BUTTON_RELEASE && event->button==3) {
		// press right button
		gtk_menu_popup (mw->menu.category.self,
		                NULL,
		                NULL,
		                NULL,
		                NULL,
		                0,
		                gtk_get_current_event_time());
		return TRUE;
	}
	return FALSE;
}


// MainWindow ----------------------------------------------------------------
void main_window_init (MainWindow* mw)
{
	GtkWidget*  scrolled;
	GtkTextBuffer*    buffer;
	GtkTreeSelection* selection;
#ifndef _WIN32
	GdkPixbuf*  icon_pixbuf;
	gchar*      icon_path;
#endif

	mw->vbox = gtk_vbox_new (FALSE, 3);
	mw->self = (GtkWindow*)gtk_window_new (GTK_WINDOW_TOPLEVEL);

	// accelerators
	mw->accelgroup = gtk_accel_group_new ();
	gtk_window_add_accel_group (mw->self, mw->accelgroup);
	gtk_accel_group_connect (mw->accelgroup, GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE, g_cclosure_new (G_CALLBACK(gtk_main_quit), NULL, NULL));
	//gtk_accel_group_lock (mw->accelgroup);
	//gtk_accel_groups_activate (G_OBJECT(mw->self), GDK_q, GDK_CONTROL_MASK);

	gtk_window_set_title (mw->self, URLGFE_TITLE);
	gtk_window_set_default_size (mw->self, 515, 350);
	view_setting_init (&mw->view_setting);
	mw->queue_ctrl = NULL;
	mw->id_cursor_changed = 0;
	mw->id_selection = 0;
	mw->id_button_event = 0;
	mw->view_setting_loading = FALSE;
	mw->download_moving = FALSE;

#ifndef _WIN32
	icon_path   = g_build_filename (DATADIR, "pixmaps", "urlgfe-icon.png", NULL);
	icon_pixbuf = gdk_pixbuf_new_from_file (icon_path, NULL);
	g_free (icon_path);
	if (icon_pixbuf)
		gtk_window_set_icon (mw->self, icon_pixbuf);
#endif

	main_menu_init (&mw->menu, mw);
	main_toolbar_init (&mw->toolbar);

	// category tree view
	mw->category_view = category_tree_view_new ();
	gtk_widget_set_size_request ((GtkWidget*)mw->category_view, 165, 100);
	scrolled = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
	                                     GTK_SHADOW_IN);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
	                                GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_container_add (GTK_CONTAINER(scrolled), GTK_WIDGET(mw->category_view));

	// create and setup TextView
	mw->text_view = (GtkTextView*)gtk_text_view_new ();
	gtk_text_view_set_left_margin (mw->text_view, 2);
	gtk_text_view_set_right_margin (mw->text_view, 2);
	gtk_text_view_set_editable (mw->text_view, FALSE);
	gtk_text_view_set_cursor_visible (mw->text_view, FALSE);
	gtk_widget_set_size_request ((GtkWidget*)mw->text_view, 35, 35);
	buffer = gtk_text_view_get_buffer (mw->text_view);
	mw->text_tag = gtk_text_buffer_create_tag (buffer, "blue_foreground",
	                                           "foreground", "blue", NULL);
	mw->message_area = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (mw->message_area),
	                                     GTK_SHADOW_IN);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mw->message_area),
	                                GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_widget_set_size_request (mw->message_area, 50, 60);
	gtk_container_add (GTK_CONTAINER(mw->message_area), GTK_WIDGET(mw->text_view));

	// pack paned
	mw->vpaned = (GtkPaned*)gtk_vpaned_new ();
	mw->hpaned = (GtkPaned*)gtk_hpaned_new ();
	gtk_paned_pack1 (mw->hpaned, (GtkWidget*)scrolled, FALSE, TRUE);
	gtk_paned_add2  (mw->hpaned, (GtkWidget*)mw->vpaned);
	gtk_paned_pack2 (mw->vpaned, (GtkWidget*)mw->message_area, FALSE, TRUE);

	// status bar + status image
	mw->status_hbox = gtk_hbox_new (FALSE, 0);
	mw->statusbar = (GtkStatusbar*) gtk_statusbar_new ();
	statusbar_set_n_selected (mw->statusbar, 0);
	mw->status_image = (GtkImage*) gtk_image_new ();
	gtk_box_pack_start (GTK_BOX (mw->status_hbox), GTK_WIDGET (mw->status_image),
	                    FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX (mw->status_hbox), GTK_WIDGET (mw->statusbar),
	                    TRUE, TRUE, 0);


	// pack to vbox
	gtk_box_pack_start (GTK_BOX (mw->vbox), mw->menu.self,
	                    FALSE, FALSE, 0);

	gtk_box_pack_start (GTK_BOX (mw->vbox), GTK_WIDGET (mw->toolbar.self),
	                    FALSE, FALSE, 0);

	gtk_box_pack_start (GTK_BOX (mw->vbox), GTK_WIDGET (mw->hpaned),
	                    TRUE, TRUE, 0);

	gtk_box_pack_start (GTK_BOX (mw->vbox), GTK_WIDGET (mw->status_hbox),
	                    FALSE, FALSE, 0);

	gtk_container_add (GTK_CONTAINER (mw->self), GTK_WIDGET (mw->vbox));

	// signal connect
	selection = gtk_tree_view_get_selection (mw->category_view);
	g_signal_connect (selection, "changed",
	                  G_CALLBACK (on_category_selection_changed), mw);
	g_signal_connect (mw->category_view, "button-release-event",
	                  G_CALLBACK(on_category_button_event), (gpointer)mw);
	g_signal_connect (mw->category_view, "row-collapsed",
	                  G_CALLBACK(on_category_row_collapsed), (gpointer)mw);

	g_signal_connect (mw->menu.view.toolbar, "toggled", G_CALLBACK (on_view_toggled), mw);
	g_signal_connect (mw->menu.view.statusbar, "toggled", G_CALLBACK (on_view_toggled), mw);
//	g_signal_connect (mw->menu.view.category_header, "toggled", G_CALLBACK (on_view_toggled), mw);
	g_signal_connect (mw->menu.view.msg_area, "toggled", G_CALLBACK (on_view_toggled), mw);
	g_signal_connect (mw->menu.view.download_rules_hint, "toggled", G_CALLBACK (on_view_toggled), mw);

/*
	g_signal_connect_swapped (mw->self, "destroy",
	                          G_CALLBACK (main_window_finalize), mw);

	selection = gtk_tree_view_get_selection (mw->category_view);
	g_signal_connect_swapped (selection, "changed",
	                          G_CALLBACK (main_window_on_selection_changed), mw);
	signal_proxy_connect_swapped (&mw->browser.dselection_signal_proxy, "changed",
	                              G_CALLBACK (main_window_on_browser_changed), mw);
*/

//	main_window_on_selection_changed (mw);
	main_window_set_category_sensitive (mw, FALSE);
	main_window_set_download_sensitive (mw, FALSE);
	gtk_widget_show_all ((GtkWidget*)mw->vbox);
}

void main_window_set_queue_ctrl (MainWindow* mw, QueueCtrl* ctrl)
{
	GtkTreeView*      treeview;
	GtkTreeSelection* selection;

	// avoid crash if mw->queue_ctrl == ctrl
	if (ctrl)
		queue_ctrl_ref (ctrl);

	if (mw->queue_ctrl) {
		treeview = mw->queue_ctrl->view;
		selection = gtk_tree_view_get_selection (treeview);
		g_signal_handler_disconnect (treeview, mw->id_cursor_changed);
		g_signal_handler_disconnect (selection, mw->id_selection);
		g_signal_handler_disconnect (treeview, mw->id_button_event);
		g_object_ref (mw->queue_ctrl->top_widget);
		gtk_container_remove (GTK_CONTAINER (mw->vpaned),
		                      mw->queue_ctrl->top_widget);
		queue_ctrl_unref (mw->queue_ctrl);
	}

	if (ctrl) {
		queue_ctrl_apply_setting (ctrl, &mw->view_setting);
		treeview = ctrl->view;
		selection = gtk_tree_view_get_selection (treeview);
		gtk_paned_add1 (mw->vpaned, ctrl->top_widget);
		mw->id_cursor_changed = g_signal_connect (treeview, "cursor-changed",
		                        G_CALLBACK(on_download_cursor_changed), mw);
		mw->id_selection = g_signal_connect (selection, "changed",
		                        G_CALLBACK(on_download_selection_changed), mw);
		mw->id_button_event = g_signal_connect (treeview, "button-press-event",
		                        G_CALLBACK(on_download_button_event), mw);
		on_download_selection_changed (selection, mw);
		gtk_tree_view_set_rules_hint (ctrl->view, mw->view_setting.download.rules_hint);
	}

	mw->queue_ctrl = ctrl;
	main_window_message_area_refresh (mw);
	main_window_statusbar_refresh (mw);
}

void main_window_set_queue_state (MainWindow* mw, gboolean queuing)
{
	if (queuing) {
//		gtk_widget_set_sensitive (mw->menu.global.start_all, FALSE);
		gtk_widget_set_sensitive (mw->menu.global.pause_all, TRUE);
		gtk_image_set_from_stock (mw->status_image, GTK_STOCK_YES, GTK_ICON_SIZE_MENU);
	} else {
		gtk_widget_set_sensitive (mw->menu.global.start_all, TRUE);
		gtk_widget_set_sensitive (mw->menu.global.pause_all, FALSE);
		gtk_image_set_from_stock (mw->status_image, GTK_STOCK_NO, GTK_ICON_SIZE_MENU);
	}
}

void main_window_finalize (MainWindow* mw)
{
	if (mw->queue_ctrl) {
		queue_ctrl_unref (mw->queue_ctrl);
	}
}

void main_window_set_download_sensitive (MainWindow* mw, gboolean sens)
{
	// tool button
	gtk_widget_set_sensitive (mw->toolbar.start, sens);
	gtk_widget_set_sensitive (mw->toolbar.stop, sens);
	gtk_widget_set_sensitive (mw->toolbar.erase, sens);
	gtk_widget_set_sensitive (mw->toolbar.property, sens);
	gtk_widget_set_sensitive (mw->toolbar.move_up, sens);
	gtk_widget_set_sensitive (mw->toolbar.move_down, sens);
	gtk_widget_set_sensitive (mw->toolbar.move_top, sens);
	gtk_widget_set_sensitive (mw->toolbar.move_bottom, sens);
	// menu item
	gtk_widget_set_sensitive (mw->menu.download.start, sens);
	gtk_widget_set_sensitive (mw->menu.download.stop, sens);
	gtk_widget_set_sensitive (mw->menu.download.erase, sens);
	gtk_widget_set_sensitive (mw->menu.download.move_to, sens);
	gtk_widget_set_sensitive (mw->menu.download.properties, sens);
	gtk_widget_set_sensitive (mw->menu.download.move_up, sens);
	gtk_widget_set_sensitive (mw->menu.download.move_down, sens);
	gtk_widget_set_sensitive (mw->menu.download.move_top, sens);
	gtk_widget_set_sensitive (mw->menu.download.move_bottom, sens);
}

void main_window_set_category_sensitive (MainWindow* mw, gboolean sens)
{
	// tool button for category
	gtk_widget_set_sensitive (mw->toolbar.category_erase, sens);
//	gtk_widget_set_sensitive (mw->toolbar.export, sens);
	// tool button
	gtk_widget_set_sensitive (mw->toolbar.create, sens);
	gtk_widget_set_sensitive (mw->toolbar.create_batch, sens);
	// download menu item
	gtk_widget_set_sensitive (mw->menu.download.create, sens);
	gtk_widget_set_sensitive (mw->menu.download.create_batch, sens);
	// category menu item
	gtk_widget_set_sensitive (mw->menu.category.erase, sens);
	gtk_widget_set_sensitive (mw->menu.category.properties, sens);
	// file menu item
	gtk_widget_set_sensitive (mw->menu.file.export_url, sens);
}

void main_window_view_set (MainWindow* mw)
{
	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mw->menu.view.toolbar),
	                                mw->view_setting.toolbar_visible);
	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mw->menu.view.statusbar),
	                                mw->view_setting.statusbar_visible);
	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mw->menu.view.msg_area),
	                                mw->view_setting.message.visible);
	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mw->menu.view.download_rules_hint),
	                                mw->view_setting.download.rules_hint);

	if (mw->view_setting.message.visible)
		gtk_widget_show (GTK_WIDGET (mw->message_area));
	else
		gtk_widget_hide (GTK_WIDGET (mw->message_area));

	if (mw->view_setting.toolbar_visible)
		gtk_widget_show (GTK_WIDGET (mw->toolbar.self));
	else
		gtk_widget_hide (GTK_WIDGET (mw->toolbar.self));

	if (mw->view_setting.statusbar_visible) {
		gtk_widget_show (GTK_WIDGET (mw->status_image));
		gtk_widget_show (GTK_WIDGET (mw->statusbar));
	} else {
		gtk_widget_hide (GTK_WIDGET (mw->status_image));
		gtk_widget_hide (GTK_WIDGET (mw->statusbar));
	}

	if (mw->queue_ctrl) {
		gtk_tree_view_set_rules_hint (mw->queue_ctrl->view, mw->view_setting.download.rules_hint);
	}
}

void main_window_view_get (MainWindow* mw)
{
	gboolean visible;

	visible = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (mw->menu.view.toolbar));
	mw->view_setting.toolbar_visible = visible;

	visible = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (mw->menu.view.statusbar));
	mw->view_setting.statusbar_visible = visible;

	visible = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (mw->menu.view.msg_area));
	mw->view_setting.message.visible = visible;

	visible = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (mw->menu.view.download_rules_hint));
	mw->view_setting.download.rules_hint = visible;
}

void main_window_view_apply (MainWindow* mw)
{
	mw->view_setting_loading = TRUE;

	main_window_view_set (mw);

	mw->view_setting_loading = FALSE;
}

// Message area
void main_window_message_area_refresh (MainWindow* mw)
{
	DownloadNode* dnode;
	GtkTreeView*  treeview;
	GtkTreeIter   iter;
	GtkTreePath*  path;
	GtkTreeModel* model;

	if (mw->queue_ctrl == NULL) {
		main_window_message_area_set (mw, NULL);
		return;
	}

	treeview = mw->queue_ctrl->view;
	gtk_tree_view_get_cursor (treeview, &path, NULL);
	if (path==NULL) {
		main_window_message_area_set (mw, NULL);
	} else {
		model = gtk_tree_view_get_model (treeview);
		gtk_tree_model_get_iter (model, &iter, path);
		gtk_tree_path_free (path);
		gtk_tree_model_get (model, &iter, 0, &dnode, -1);
		main_window_message_area_set (mw, dnode);
	}
}

void main_window_message_area_set (MainWindow* mw, DownloadNode* dnode)
{
	GtkTextBuffer*   textbuf;

	textbuf = gtk_text_view_get_buffer (mw->text_view);
	gtk_text_buffer_set_text (textbuf, "", 0);

	if (dnode==NULL)
		return;

	if (mw->view_setting.message.filename.visible) {
		text_buffer_add_text (textbuf, mw->text_tag, _("Filename:"),
		                      dnode->filename, TRUE);
	}
	if (mw->view_setting.message.directory.visible) {
		text_buffer_add_text (textbuf, mw->text_tag, _("Directory:"),
		                      dnode->directory, TRUE);
	}
	if (mw->view_setting.message.url.visible) {
		text_buffer_add_text (textbuf, mw->text_tag, _("URL:"),
		                      dnode->url, TRUE);
	}
	if (mw->view_setting.message.message.visible) {
		text_buffer_add_text (textbuf, mw->text_tag, _("Last Message:"),
		                      (dnode->message) ? dnode->message : _("None"),
		                      FALSE);
	}
}

// Status bar

void main_window_statusbar_refresh (MainWindow* mw)
{
	int  n_selected;
	GtkTreeView*  treeview;
	GtkTreeSelection* selection;

	if (mw->queue_ctrl == NULL) {
		statusbar_set_n_selected (mw->statusbar, 0);
		return;
	}

	treeview = mw->queue_ctrl->view;
	selection = gtk_tree_view_get_selection (treeview);
	n_selected = gtk_tree_selection_count_selected_rows (selection);
	statusbar_set_n_selected (mw->statusbar, n_selected);
}


static void main_menu_init (MainMenu* mm, MainWindow* mw)
{
	GtkWidget* image;
	GtkWidget* menu_item;

	mm->self = gtk_menu_bar_new ();


	// File Menu ---------------------------------------------------------
	mm->file.self = (GtkMenu*)gtk_menu_new ();

	mm->file.import_html = gtk_image_menu_item_new_with_mnemonic (_("Import _HTML file..."));
	image = gtk_image_new_from_stock (GTK_STOCK_CONVERT, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->file.import_html, image);

	mm->file.import_url = gtk_image_menu_item_new_with_mnemonic (_("Import _URLs..."));
	image = gtk_image_new_from_stock (GTK_STOCK_CONVERT, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->file.import_url, image);

	mm->file.export_url = gtk_image_menu_item_new_with_mnemonic (_("_Export URLs..."));
	image = gtk_image_new_from_stock (GTK_STOCK_CONVERT, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->file.export_url, image);

	mm->file.save_all = gtk_image_menu_item_new_with_mnemonic (_("_Save All"));
	image = gtk_image_new_from_stock (GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->file.save_all, image);

	mm->file.quit = gtk_image_menu_item_new_from_stock (GTK_STOCK_QUIT, mw->accelgroup);

//	menu.append( gtk_tearoff_menu_item_new() );
	gtk_menu_append (mm->file.self, mm->file.import_html);
	gtk_menu_append (mm->file.self, mm->file.import_url);
	gtk_menu_append (mm->file.self, mm->file.export_url);
	gtk_menu_append (mm->file.self, mm->file.save_all);
	gtk_menu_append (mm->file.self, mm->file.quit);

	menu_item = gtk_menu_item_new_with_mnemonic (_("_File"));
	gtk_menu_item_set_submenu ((GtkMenuItem*)menu_item, (GtkWidget*)mm->file.self);
	gtk_menu_shell_append ((GtkMenuShell *)mm->self, menu_item);


	// Category Menu -----------------------------------------------------
	mm->category.self = (GtkMenu*)gtk_menu_new ();

	mm->category.create = gtk_image_menu_item_new_with_mnemonic (_("_New..."));
	image = gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->category.create, image);

	mm->category.erase = gtk_image_menu_item_new_with_mnemonic (_("_Erase"));
	image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->category.erase, image);

	mm->category.properties = gtk_image_menu_item_new_with_mnemonic (_("_Properties..."));
	image = gtk_image_new_from_stock (GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->category.properties ,image);

	mm->category.set_default = gtk_menu_item_new_with_mnemonic (_("_Default of new Category..."));

//	menu.append( gtk_tearoff_menu_item_new() );
	gtk_menu_append (mm->category.self, mm->category.create);
	gtk_menu_append (mm->category.self, mm->category.erase);
	gtk_menu_append (mm->category.self, mm->category.properties);
	gtk_menu_append (mm->category.self, mm->category.set_default);
//	gtk_menu_append (mm->category.self, gtk_separator_menu_item_new() );

	menu_item = gtk_menu_item_new_with_mnemonic (_("_Category"));
	gtk_menu_item_set_submenu ((GtkMenuItem*)menu_item, (GtkWidget*)mm->category.self);
	gtk_menu_shell_append ((GtkMenuShell *)mm->self, menu_item);


	// Download Menu -----------------------------------------------------
	mm->download.self = (GtkMenu*)gtk_menu_new ();

	mm->download.create = gtk_image_menu_item_new_with_mnemonic (_("_New Download..."));
	image = gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.create, image);

	mm->download.create_batch = gtk_image_menu_item_new_with_mnemonic (_("_Add Batch Download..."));
	image = gtk_image_new_from_stock (GTK_STOCK_SORT_ASCENDING, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.create_batch, image);

	mm->download.erase = gtk_image_menu_item_new_with_mnemonic(_("_Erase"));
	image = gtk_image_new_from_stock(GTK_STOCK_DELETE, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.erase, image);

	mm->download.move_to = gtk_image_menu_item_new_with_mnemonic(_("_Move To..."));
	image = gtk_image_new_from_stock(GTK_STOCK_DND_MULTIPLE, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.move_to, image);

	mm->download.move_up = gtk_image_menu_item_new_with_mnemonic(_("Move _Up"));
	image = gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.move_up, image);

	mm->download.move_down = gtk_image_menu_item_new_with_mnemonic(_("Move _Down"));
	image = gtk_image_new_from_stock(GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.move_down, image);

	mm->download.move_top = gtk_image_menu_item_new_with_mnemonic(_("Move _Top"));
	image = gtk_image_new_from_stock(GTK_STOCK_GOTO_TOP, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.move_top, image);

	mm->download.move_bottom = gtk_image_menu_item_new_with_mnemonic(_("Move _Bottom"));
	image = gtk_image_new_from_stock(GTK_STOCK_GOTO_BOTTOM, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.move_bottom, image);

	mm->download.start = gtk_image_menu_item_new_with_mnemonic(_("_Start"));
	image = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.start, image);

	mm->download.stop  = gtk_image_menu_item_new_with_mnemonic(_("St_op"));
	image = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.stop ,image);

	mm->download.properties = gtk_image_menu_item_new_with_mnemonic(_("_Properties..."));
	image = gtk_image_new_from_stock(GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->download.properties, image);

//	menu.append( gtk_tearoff_menu_item_new() );
	gtk_menu_append (mm->download.self, mm->download.create);
	gtk_menu_append (mm->download.self, mm->download.create_batch);
	gtk_menu_append (mm->download.self, mm->download.erase);
	gtk_menu_append (mm->download.self, gtk_separator_menu_item_new() );
	gtk_menu_append (mm->download.self, mm->download.move_to);
	gtk_menu_append (mm->download.self, mm->download.move_up);
	gtk_menu_append (mm->download.self, mm->download.move_down);
	gtk_menu_append (mm->download.self, mm->download.move_top);
	gtk_menu_append (mm->download.self, mm->download.move_bottom);
	gtk_menu_append (mm->download.self, gtk_separator_menu_item_new() );
	gtk_menu_append (mm->download.self, mm->download.start);
	gtk_menu_append (mm->download.self, mm->download.stop);
	gtk_menu_append (mm->download.self, mm->download.properties);

	menu_item = gtk_menu_item_new_with_mnemonic(_("_Download"));
	gtk_menu_item_set_submenu ((GtkMenuItem*)menu_item, (GtkWidget*)mm->download.self);
	gtk_menu_shell_append ((GtkMenuShell *)mm->self, menu_item);


	// View Menu ---------------------------------------------------------
	mm->view.self = (GtkMenu*)gtk_menu_new ();

	mm->view.toolbar = gtk_check_menu_item_new_with_mnemonic (_("_Toolbar"));
	mm->view.statusbar = gtk_check_menu_item_new_with_mnemonic (_("_Status Bar"));

//	mm->view.category_header = gtk_check_menu_item_new_with_mnemonic (_("_Category Header"));
	mm->view.msg_area = gtk_check_menu_item_new_with_mnemonic (_("_Message Area"));
	mm->view.msg_area_items = gtk_menu_item_new_with_mnemonic (_("M_essage Items..."));

	mm->view.download_rules_hint = gtk_check_menu_item_new_with_mnemonic (_("Download _Rules Hint"));
	mm->view.columns = gtk_menu_item_new_with_mnemonic (_("Download C_olumns..."));

	gtk_menu_append (mm->view.self, mm->view.toolbar);
	gtk_menu_append (mm->view.self, mm->view.statusbar);
	gtk_menu_append (mm->view.self, gtk_separator_menu_item_new() );
//	gtk_menu_append (mm->view.self, mm->view.category_header);
	gtk_menu_append (mm->view.self, mm->view.msg_area);
	gtk_menu_append (mm->view.self, mm->view.msg_area_items);
	gtk_menu_append (mm->view.self, gtk_separator_menu_item_new() );
	gtk_menu_append (mm->view.self, mm->view.download_rules_hint);
	gtk_menu_append (mm->view.self, mm->view.columns);

	menu_item = gtk_menu_item_new_with_mnemonic (_("_View"));
	gtk_menu_item_set_submenu ((GtkMenuItem*)menu_item, (GtkWidget*)mm->view.self);
	gtk_menu_shell_append ((GtkMenuShell *)mm->self, menu_item);


	// Global Menu -------------------------------------------------------
	mm->global.self = (GtkMenu*)gtk_menu_new ();

	mm->global.start_all = gtk_image_menu_item_new_with_mnemonic (_("_Start All"));
	image = gtk_image_new_from_stock (GTK_STOCK_EXECUTE, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->global.start_all, image);
	mm->global.pause_all = gtk_image_menu_item_new_with_mnemonic (_("_Pause All"));
	image = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->global.pause_all, image);

//	mm->global.start_queuing = gtk_image_menu_item_new_with_mnemonic (_("S_tart Queuing"));
//	image = gtk_image_new_from_stock (GTK_STOCK_YES, GTK_ICON_SIZE_MENU);
//	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->global.start_queuing, image);
//	mm->global.pause_queuing = gtk_image_menu_item_new_with_mnemonic (_("P_ause Queuing"));
//	image = gtk_image_new_from_stock (GTK_STOCK_NO, GTK_ICON_SIZE_MENU);
//	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->global.pause_queuing, image);

	mm->global.setting = gtk_menu_item_new_with_mnemonic (_("_Global Setting..."));

	gtk_menu_append (mm->global.self, mm->global.start_all);
	gtk_menu_append (mm->global.self, mm->global.pause_all);
//	gtk_menu_append (mm->global.self, gtk_separator_menu_item_new() );
//	gtk_menu_append (mm->global.self, mm->global.start_queuing);
//	gtk_menu_append (mm->global.self, mm->global.pause_queuing);
	gtk_menu_append (mm->global.self, gtk_separator_menu_item_new() );
	gtk_menu_append (mm->global.self, mm->global.setting);

	menu_item = gtk_menu_item_new_with_mnemonic (_("_Global"));
	gtk_menu_item_set_submenu ((GtkMenuItem*)menu_item, (GtkWidget*)mm->global.self);
	gtk_menu_shell_append ((GtkMenuShell *)mm->self, menu_item);


	// Help Menu ---------------------------------------------------------
	mm->help.self = (GtkMenu*)gtk_menu_new ();
	mm->help.about_urlgfe = gtk_image_menu_item_new_with_mnemonic (_("_About Urlgfe..."));
	image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_MENU);
	gtk_image_menu_item_set_image ((GtkImageMenuItem*)mm->help.about_urlgfe, image);

	gtk_menu_append (mm->help.self, mm->help.about_urlgfe);

	menu_item = gtk_menu_item_new_with_mnemonic(_("_Help"));
	gtk_menu_item_set_submenu ((GtkMenuItem*)menu_item, (GtkWidget*)mm->help.self);
	gtk_menu_shell_append ((GtkMenuShell *)mm->self, menu_item);
}

// utility for create button
static GtkWidget* toolbar_item_new (const gchar* stock_id,
                                    const gchar* tip_str,
                                    GtkTooltips* tips)
{
	GtkWidget* button;
	GtkWidget* image;

	button = gtk_button_new();
	image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_SMALL_TOOLBAR);

	gtk_container_add (GTK_CONTAINER(button), image);
	gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
	GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);

	gtk_tooltips_set_tip (tips, button, tip_str, NULL);

	return button;
}

static void main_toolbar_init (MainToolbar* mt)
{
	GtkTooltips* tips;
	GtkBox*      hbox;

	mt->self = gtk_hbox_new (FALSE, 0);
	hbox = GTK_BOX (mt->self);

	tips = gtk_tooltips_new ();

	// Create Category
	mt->category_create = toolbar_item_new (GTK_STOCK_DND_MULTIPLE,
	                                        _("Create a Category"),
	                                        tips);
	gtk_box_pack_start (hbox, mt->category_create, FALSE, FALSE, 1);

	// Erase Category
	mt->category_erase = toolbar_item_new (GTK_STOCK_CLOSE,
	                                       _("Delete a Category"),
	                                       tips);
	gtk_box_pack_start (hbox, mt->category_erase, FALSE, FALSE, 1);

	// Import Category
//	mt->import =  toolbar_item_new (GTK_STOCK_CONVERT,
//	                                _("Import ..."),
//	                                tips);
//	gtk_box_pack_start (hbox, mt->import, FALSE, FALSE, 1);

	// import Category
//	mt->export =  toolbar_item_new (GTK_STOCK_CONVERT,
//	                                _("Export ..."),
//	                                tips);
//	gtk_box_pack_start (hbox, mt->export, FALSE, FALSE, 1);

	// add separator
	gtk_box_pack_start (hbox, gtk_vseparator_new (), FALSE, FALSE, 1);

	// Start Download
	mt->start = toolbar_item_new (GTK_STOCK_MEDIA_PLAY,
	                              _("Start Automatically"),
	                              tips);
	gtk_box_pack_start (hbox, mt->start, FALSE, FALSE, 1);

	// Stop Download
	mt->stop = toolbar_item_new (GTK_STOCK_MEDIA_PAUSE, _("Stop"), tips);
	gtk_box_pack_start (hbox, mt->stop, FALSE, FALSE, 1);

	// Create Download
	mt->create = toolbar_item_new (GTK_STOCK_NEW,
	                               _("Create new download"),
	                               tips);
	gtk_box_pack_start (hbox, mt->create, FALSE, FALSE, 1);

	// Create batch
	mt->create_batch = toolbar_item_new (GTK_STOCK_SORT_ASCENDING,
	                                     _("Add Batch Download"),
	                                     tips);
	gtk_box_pack_start (hbox, mt->create_batch, FALSE, FALSE, 1);

	// Delete
	mt->erase = toolbar_item_new (GTK_STOCK_DELETE,
	                              _("Delete selected jobs"),
	                              tips);
	gtk_box_pack_start (hbox, mt->erase, FALSE, FALSE, 1);

	// Property
	mt->property = toolbar_item_new (GTK_STOCK_PROPERTIES,
	                                 _("Properties"),
	                                 tips);
	gtk_box_pack_start (hbox, mt->property, FALSE, FALSE, 1);

	// Move up
	mt->move_up = toolbar_item_new (GTK_STOCK_GO_UP,
	                                _("Move Up"),
	                                tips);
	gtk_box_pack_start (hbox, mt->move_up, FALSE, FALSE, 1);

	// Move down
	mt->move_down = toolbar_item_new (GTK_STOCK_GO_DOWN,
	                                  _("Move Down"),
	                                  tips);
	gtk_box_pack_start (hbox, mt->move_down, FALSE, FALSE, 1);

	// Move top
	mt->move_top = toolbar_item_new (GTK_STOCK_GOTO_TOP,
	                                 _("Move Top"),
	                                 tips);
	gtk_box_pack_start (hbox, mt->move_top, FALSE, FALSE, 1);

	// Move bottom
	mt->move_bottom = toolbar_item_new (GTK_STOCK_GOTO_BOTTOM,
	                                    _("Move Bottom"),
	                                    tips);
	gtk_box_pack_start (hbox, mt->move_bottom, FALSE, FALSE, 1);

	gtk_widget_show_all (mt->self);
}

// utility functions ------------------------------------------------

// utility for GtkStatusbar
static void statusbar_set_n_selected (GtkStatusbar* sb, guint n_selected)
{
	static guint last_id=0;
	gchar* string;

	if (last_id)
		gtk_statusbar_pop (sb, last_id);

	string = g_strdup_printf (_("Selected %d files"), n_selected);
	last_id = gtk_statusbar_get_context_id (sb, string);
	gtk_statusbar_push (sb, last_id, string);
	g_free (string);
}

// utility for GtkTextBuffer
static void text_buffer_add_text (GtkTextBuffer* buffer,
                                  GtkTextTag* text_tag,
                                  gchar *name, gchar *str,
                                  gboolean next_line)
{
	GtkTextIter    text_iter;
	GtkTextIter    text_iter2;
	GtkTextMark*   mark;

	gtk_text_buffer_get_end_iter (buffer, &text_iter2);
	mark = gtk_text_buffer_create_mark (buffer, NULL, &text_iter2, TRUE);
	gtk_text_buffer_insert (buffer, &text_iter2, name, -1);
	// apply tag
	gtk_text_buffer_get_end_iter (buffer, &text_iter2);
	gtk_text_buffer_get_iter_at_mark (buffer, &text_iter, mark);
	gtk_text_buffer_apply_tag (buffer, text_tag,
	                           &text_iter, &text_iter2);
	gtk_text_buffer_delete_mark (buffer, mark);

	gtk_text_buffer_insert (buffer, &text_iter2, (str) ? str : "", -1);
	// to next line
	if (next_line) {
		gtk_text_buffer_get_end_iter (buffer, &text_iter2);
		gtk_text_buffer_insert (buffer, &text_iter2, "\n", -1);
	}
}

// End of utility functions =========================================
